home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
edit
/
xvisrc.zip
/
OS2VIO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-28
|
18KB
|
857 lines
#ifndef lint
static char *sccsid = "@(#)os2vio.c 2.1 (Chris & John Downey) 7/29/92";
#endif
/***
* program name:
xvi
* function:
PD version of UNIX "vi" editor, with extensions.
* module name:
os2vio.c
* module function:
OS/2 system interface module.
This is a character-based implementation using the VIO & KBD
families of system calls. It doesn't use the Presentation Manager
but, on OS/2 version 1.* at least, it can be made to work in a PM
shell window by using markexe (see makefile.os2).
Like the MS-DOS version, this one saves the screen contents &
restores them when it exits.
Currently, the mouse input code doesn't work, & so is commented
out. I suspect that, if we want to have both mouse & keyboard
input, we have to use a device monitor, or develop a real PM
implementation.
* history:
STEVIE - ST Editor for VI Enthusiasts, Version 3.10
Originally by Tim Thompson (twitch!tjt)
Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
Heavily modified by Chris & John Downey
***/
#include "xvi.h"
#define NOMOUSE
#ifdef __ZTC__
/*
* Set default stack size.
*
* See i286.asm for an explanation of why it has to be so big.
*/
unsigned _stack = 44 * 1024;
#endif
/*
* These are globals which are set by the system interface or terminal
* interface module, & used for various purposes throughout the rest
* of xvi.
*
* Number of rows & columns in the current window.
*/
unsigned Rows,
Columns;
/*
* Current position for screen writes.
*/
unsigned char virt_row,
virt_col;
/*
* Screen cell (character & attribute): current colour is stored here.
*/
unsigned char curcell [2];
/*
* Time of last keypress or mouse button press (or garbage if
* (keystrokes < PSVKEYS)).
*
* This should only be referenced within a thread's critical section.
* Referencing a 32-bit variable is not generally an atomic operation
* on the 80286.
*/
static volatile clock_t lastevent;
#ifndef NOMOUSE
/*
* This is FALSE if we don't appear to have a mouse driver.
*/
static bool_t usemouse;
/*
* Our logical mouse handle.
*/
static HMOU mousenum;
#else /* NOMOUSE */
# define usemouse FALSE
#endif /* NOMOUSE */
#ifndef NOMOUSE
/*
* Hide mouse cursor.
*/
static void
hidemouse()
{
NOPTRRECT r;
r.row = r.col = 0;
r.cRow = Rows - 1;
r.cCol = Columns - 1;
(void) MouRemovePtr((PNOPTRRECT) &r, mousenum);
}
#endif /* NOMOUSE */
/*
* Show mouse cursor. (This is for symmetry with hidemouse().)
*/
#define showmouse() ((void) MouDrawPtr(mousenum))
static long semvec [2];
/*
* This semaphore needs to be acquired by a thread before it enters a
* critical region.
*/
#define control ((HSEM)(long FAR *)&semvec[0])
/*
* This semaphore is used for communication between the main thread &
* the thread which handles automatic buffer preservation. It should
* be clear when (keystrokes >= PSVKEYS), otherwise it should be set.
*/
#define psvsema ((HSEM)(long FAR *)&semvec[1])
#ifndef NOMOUSE
static void
mousehandler()
{
for (;;) {
MOUEVENTINFO m;
unsigned short status;
clock_t start;
#if 0
if (MouGetDevStatus((PUSHORT) &status, mousenum) != 0
||
(status & (MOUSE_UNSUPPORTED_MODE | MOUSE_DISABLED))
) {
hidemouse();
(void) MouClose(mousenum);
DosExit(EXIT_THREAD, 0);
}
#endif
status = MOU_WAIT;
MouReadEventQue((PMOUEVENTINFO) &m, (PUSHORT) &status, mousenum);
/*
* If we don't get the control semaphore immediately,
* we do nothing. Delayed responses to mouse button
* presses could be confusing.
*/
#if 0
start = clock();
#endif
if (DosSemRequest(control, SEM_IMMEDIATE_RETURN) != 0)
continue;
#if 0
if (clock() != start) {
(void) fprintf(stderr, "mouse thread: %d\n", __LINE__);
DosSemClear(control);
continue;
}
#endif
/*
* Start of critical section.
*/
if (++keystrokes >= PSVKEYS)
lastevent = clock();
if (State == NORMAL &&
(m.fs & (MOUSE_BN1_DOWN | MOUSE_BN2_DOWN | MOUSE_BN3_DOWN))) {
hidemouse();
mouseclick(m.row, m.col);
showmouse();
}
/*
* End of critical section.
*/
DosSemClear(control);
}
}
#endif /* NOMOUSE */
/*
* Macro to convert clock ticks to milliseconds.
*/
#if CLK_TCK == 1000
# define CLK2MS(c) (c)
#else
# if CLK_TCK < 1000
# define CLK2MS(c) ((c) * (1000 / CLK_TCK))
# else
# define CLK2MS(c) ((c) / (CLK_TCK / 1000))
# endif /* CLK_TCK > 1000 */
#endif /* CLK_TCK != 1000 */
/*
* Number of keystrokes or mouse button presses since the last buffer
* preservation.
*/
volatile int keystrokes;
/*
* This function handles automatic buffer preservation. It runs in its
* own thread, which is only awake when keystrokes >= PSVKEYS and the
* main thread is waiting for keyboard input. Even then, it spends
* most of its time asleep.
*/
static void FAR
psvhandler()
{
for (;;) {
long sleeptime;
DosSemWait(psvsema, SEM_INDEFINITE_WAIT);
DosSemRequest(control, SEM_INDEFINITE_WAIT);
/*
* Start of critical section.
*/
if (keystrokes < PSVKEYS) {
sleeptime = 0;
/*
* If we haven't had at least PSVKEYS
* keystrokes, psvsema should be set.
*/
DosSemSet(psvsema);
} else if ((sleeptime = (long) Pn(P_preservetime) * 1000 -
CLK2MS(clock() - lastevent)) <= 0) {
/*
* If Pn(P_presevetime) seconds haven't yet
* elapsed, sleep until they should have - but
* NOT within the critical section (!).
*
* Otherwise do automatic preserve.
*
* do_preserve() should reset keystrokes to 0.
*/
(void) do_preserve();
sleeptime = 0;
}
/*
* End of critical section.
*/
DosSemClear(control);
/*
* Sleep if we have to.
*/
if (sleeptime != 0)
DosSleep(sleeptime);
}
}
/*
* inchar() - get a character from the keyboard.
*
* Timeout not implemented yet for OS/2.
*/
int
inchar(long mstimeout)
{
for (;;) {
KBDKEYINFO k;
bool_t mstatus,
psvstatus;
flush_output();
mstatus = (usemouse && State == NORMAL);
psvstatus = (keystrokes >= PSVKEYS);
/*
* We don't have to give control to any other thread
* if neither of these conditions is true.
*/
if (mstatus || psvstatus) {
#ifndef NOMOUSE
if (mstatus)
showmouse();
#endif
if (psvstatus && DosSemWait(psvsema, SEM_IMMEDIATE_RETURN)
== ERROR_SEM_TIMEOUT) {
/*
* If psvsema is set, clear it.
*/
DosSemClear(psvsema);
}
DosSemClear(control);
}
/*
* Start of non-critical section.
*
* Wait for character from keyboard.
*/
KbdCharIn((PKBDKEYINFO) &k, IO_WAIT, 0);
/*
* End of non-critical section.
*/
if (mstatus || psvstatus) {
DosSemRequest(control, SEM_INDEFINITE_WAIT);
#ifndef NOMOUSE
if (mstatus)
hidemouse();
#endif
}
if (++keystrokes >= PSVKEYS)
lastevent = clock();
/*
* Now deal with the keypress information.
*/
if ((unsigned char) k.chChar == (unsigned char) 0xe0) {
/*
* It's (probably) a function key.
*/
if (k.chScan == 0x53)
/*
* It's the delete key.
*/
return State == NORMAL ? 'x' : '\b';
/* else */
if (State == NORMAL) {
/*
* Assume it must be a function key.
*/
switch (k.chScan) {
case 0x3b: return(K_HELP);
/* F1 key */
case 0x47: return('H');
/* home key */
case 0x48: return('k');
/* up arrow key */
case 0x49: return(CTRL('B'));
/* page up key */
case 0x4b: return('\b');
/* left arrow key */
case 0x4d: return(' ');
/* right arrow key */
case 0x4f: return('L');
/* end key */
case 0x50: return('j');
/* down arrow key */
case 0x51: return(CTRL('F'));
/* page down key */
case 0x52: return('i');
/* insert key */
default:
/* just ignore it ... */
continue;
}
/*
* If we aren't in command mode, 0xe0
* is a perfectly legitimate
* character, & we can't really tell
* whether or not it's supposed to be
* a function key, so we just have to
* return it as is.
*/
}
}
return (unsigned char) k.chChar;
}
}
void
outchar(int c)
{
curcell [0] = c;
VioWrtNCell((PBYTE) curcell, 1,